import { Injectable, Logger } from '@nestjs/common';
import { Item } from '@prisma/client';
import { PrismaService } from 'src/prisma/prisma.service';
import { ItemDto, WithoutFileDto } from './dto/items';
import { MemoryStoredFile } from 'nestjs-form-data';

@Injectable()
export class ItemsService {
  private readonly logger = new Logger('itemsService');
  constructor(private readonly prisma: PrismaService) {}

  async deleteItemById(id: number) {
    return this.prisma.item.delete({ where: { id } });
  }

  async getAllItems(page: number = 0) {
    const pageSize = 200;
    return this.prisma.item.findMany({
      take: pageSize,
      select: {
        id: true,
        name: true,
        description: true,
        category: true,
        price: true,
      },
      skip: page * pageSize,
    });
  }

  async createCategory(categoryName: string) {
    return this.prisma.itemCategory.create({ data: { name: categoryName } });
  }

  async getByCategoryId(categoryId: number) {
    const items = await this.prisma.item.findMany({
      where: {
        categoryId,
      },
    });

    return items;
  }

  async getItemsByIds(ids: number[]) {
    const items = await this.prisma.item.findMany({
      where: {
        id: {
          in: ids,
        },
      },
      select: {
        id: true,
        name: true,
        description: true,
        category: true,
        price: true,
      },
    });

    return items;
  }

  async deleteCategoryById(id: number) {
    return this.prisma.itemCategory.delete({ where: { id } });
  }

  async getAllCategories() {
    const categories = await this.prisma.itemCategory.findMany();

    return categories;
  }

  async getItemById(id: number) {
    return this.prisma.$transaction(async (tx) => {
      const item = await this.prisma.item.findUnique({
        where: { id },
        include: { category: true },
      });

      const now = new Date();
      const oneMonthAgo = new Date();
      oneMonthAgo.setMonth(now.getMonth() - 1);
      const m = {};

      const orderItems = await this.prisma.orderItem.findMany({
        where: {
          menuItemId: id,
          order: {
            createdAt: {
              gte: oneMonthAgo,
            },
          },
        },
        include: { order: true },
      });

      orderItems.forEach((item) => {
        const date = item.order.createdAt;
        const day = String(date.getDate()).padStart(2, '0');
        const month = String(date.getMonth() + 1).padStart(2, '0'); // Месяцы в JS начинаются с 0
        const year = date.getFullYear();
        const finalDate = `${day}.${month}.${year}`;

        if (m[finalDate]) {
          m[finalDate] += 1;
        } else {
          m[finalDate] = 1;
        }
      });

      return { ...item, stat: m };
    });
  }

  async createItem(dto: WithoutFileDto, photo?: MemoryStoredFile) {
    const d = {
      ...dto,
      price: dto.price && Number.parseFloat(dto.price),
      categoryId: Number.parseInt(dto.categoryId),
      photo: photo.buffer,
      file: undefined,
    };

    const item = await this.prisma.item.create({
      data: {
        ...d,
        categoryId: d.categoryId,
      },
      select: { id: true },
    });

    return item.id;
  }

  async updateItemById(
    id: number,
    dto: Partial<WithoutFileDto>,
    photo?: MemoryStoredFile,
  ) {
    const data = {
      ...dto,
      price: dto.price && Number.parseFloat(dto.price),
      categoryId: Number.parseInt(dto.categoryId),
      photo: photo ? photo.buffer : undefined,
      file: undefined,
    };

    await this.prisma.item.update({
      where: { id },
      data: {
        ...data,
        categoryId: undefined,
      },
    });

    if (data.categoryId)
      await this.prisma.item.update({
        where: { id },
        data: {
          category: {
            connect: { id: data.categoryId },
          },
        },
      });
  }
}
